﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using Autofac;
using Autofac.Integration.Mvc;
using Inovout.Component;
using Inovout.Descriptor;
using Inovout.Runtime;
using System.IO;
using Common.Logging;

namespace Inovout.Web.Mvc
{
    [Authorize]
    public class BaseController : Controller
    {
        protected readonly ILog log;
        protected BaseController()
        {
            this.log = LogManager.GetLogger(this.GetType());
        }
        protected TService GetService<TService>()
        {
            return AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<TService>();
        }
        protected TResult ExecuteService<TService, TResult>(Func<TService, TResult> serviceExecutor)
        {
            return serviceExecutor(GetService<TService>());
        }
        protected void ExecuteService<TService>(Action<TService> serviceExecutor)
        {
            serviceExecutor(GetService<TService>());
        }
        protected Task<TResult> ExecuteServiceAsync<TService, TResult>(Func<TService, TResult> serviceExecutor)
        {
            return TaskHelper.Run((componentResolver) =>
            {
                return serviceExecutor(componentResolver.Resolve<TService>());
            });
        }
        protected Task ExecuteServiceAsync<TService>(Action<TService> serviceExecutor)
        {
            return TaskHelper.Run((componentResolver) =>
            {
                serviceExecutor(componentResolver.Resolve<TService>());
            });
        }
        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.Initialize(requestContext);
            ViewBag.ReturnUrl = Request.QueryString["returnUrl"];
            InitializeDataSources();
        }

        protected virtual void InitializeDataSources()
        {
        }

        #region Title
        protected static readonly string PageTitleKey = "page.title";
        static BaseController()
        {
            IApplication application = ComponentRegistry.Resolve<IApplication>();
            if (!application.Properties.TryGetValue(PageTitleKey, out DefaultTitleFormat))
            {
                DefaultTitleFormat = "{0}{1}";
            }
        }
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            var controllerDescriptor = TypeDescriptor.Get(filterContext.Controller.GetType());
            string controllerAlias = controllerDescriptor.Alias;
            string actionAlias = AliasHelper.GetName(filterContext.ActionDescriptor.GetCustomAttributes(typeof(AliasAttribute), true).Cast<AliasAttribute>().SingleOrDefault(),
                filterContext.ActionDescriptor.GetCustomAttributes(typeof(DisplayAttribute), true).Cast<DisplayAttribute>().SingleOrDefault(),
           ((IMethodInfoActionDescriptor)filterContext.ActionDescriptor).MethodInfo);
            if (string.IsNullOrEmpty(ViewBag.Title))
            {
                ViewBag.Title = string.Format(TitleFormat, controllerAlias, actionAlias);
            }
        }
        private static string DefaultTitleFormat;
        protected virtual string TitleFormat { get { return DefaultTitleFormat; } }

        #endregion
        protected virtual ActionResult RedirectToReturnUrl(string returnUrl = null)
        {
            returnUrl = returnUrl ?? ViewBag.ReturnUrl;
            if (string.IsNullOrEmpty(returnUrl))
            {
                return RedirectToAction("Index");//, new { id = model.Id });
            }
            else
            {
                return Redirect(returnUrl);
            }
        }
        #region JsonResult
        protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
        {
            return new JsonNetResult
            {
                Data = data,
                ContentType = contentType,
                ContentEncoding = contentEncoding,
                JsonRequestBehavior = behavior
            };
        }
        protected virtual JsonResult Json<TContainerType>(TContainerType data)
        {
            return Json<TContainerType>(data, null, null);
        }
        protected virtual JsonResult Json<TContainerType>(TContainerType data, string contentType, Encoding contentEncoding)
        {
            return new JsonNetResult
            {
                Data = data,
                ContentType = contentType,
                ContentEncoding = contentEncoding,
                ContainerType = typeof(TContainerType)
            };
        }
        #endregion

        [Alias("上传"), AllowAnonymous]
        public virtual ActionResult Upload()
        {
            return View();
        }
        protected void StoreFile(Action<string> import)
        {
            string uploadFilesPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadFiles");
            if (!Directory.Exists(uploadFilesPath))
            {
                Directory.CreateDirectory(uploadFilesPath);
            }

            for (int i = 0; i < Request.Files.Count; i++)
            {
                var postFile = Request.Files[i];
                string fileName = postFile.FileName;
                string uploadFileName = Path.Combine(uploadFilesPath, Path.GetFileNameWithoutExtension(fileName) +
                    DateTime.Now.ToString("yyyyMMddhhmmss") + Path.GetExtension(fileName));
                postFile.SaveAs(uploadFileName);
                try
                {
                    import(uploadFileName);
                }
                catch
                {
                    ModelState.AddModelError(postFile.FileName, postFile.FileName + "不是正常的Excel，请尝试打开Excel另存为Excel2003格式,g再重新上传！");
                }
            }
        }


        public ActionResult Error(Exception exception)
        {

            return Error(exception.Message, exception);
        }

        public ActionResult Error(string message, Exception exception = null)
        {
            if (exception == null)
            {
                log.Error(message);
            }
            else
            {
                log.Error(message, exception);
            }
            return Error(message);
        }

    }
}
